This disk contains the entries for the first Apple II Software Enthusiasts two-liners programming exhibition of 2020! The theme for this exhibition was GAMES and I think you'll agree, all of these entries are amazing in their own right! PLEASE run the games and have fun with them. You are also highly encouraged to LIST the games to see who wrote them and how they crammed so much awesomeness into two lines of Applesoft BASIC!

Most games require joystick to play. Where provided, instructions (or other interesting notes) from the authors were included below!

PLEASE NOTE: THE CONTENTS ON THESE IMAGES ARE COPYRIGHT BY THEIR RESPECTIVE AUTHORS. YOU MAY NOT SELL OR REDISTRIBUTE THESE GAMES COMMERICIALLY WITHOUT PRIOR WRITTEN PERMISSION OF EACH SPECIFIC AUTHORS.

===

Mario Girders -- By Francois Vander Linden

The game is called "Mario Girders" and you control ... the girders (for obvious copyright reasons) ....
Help Mario reach the other end of the screen: use your crane to grab the girders on the ground and place them so that Mario doesn't fall to a certain death ...

Use paddle #1 (Joystick Y axis) to move your crane up/down... when your crane reaches a girder it automatically grabs it ... press button #0 to place/fix the girder so that Mario doesn't fall and be ready to reach the next girder. 10 levels of mega fun with infinite lives (you have to provide the infinite will to finish the game) .... How FAR can you go ??
Trick: every time you push button 0, even if you have no girders left, Mario will speed up ...

===

NORT by Brett Butler: ok, here's an official 2-liner submission. It's an 80's Arcade game in demo mode before you put a quarter in. It's called NORT! 

It's an 80's Arcade game in demo mode before you put a quarter in. 
You are NORT and your enemy is MURT and you are both trapped in an Arcade room filled with cocktail arcade games laid out in a grid.
Arcade Box Art included.

Your Enemy MURT can transport through the arcade room's walls, but you can't. Additionally, evil MURT can move diagonally & you can't. Run into MURT to take away his game tokens & increase your score. You start in a safe Arcade Entrance in the top-left galactic quadrant, but be careful entering this digital arcade room! If MURT runs over you, you may see a carcass on the ground. If you can, go pick that mess up. Use arrow keys to move. ps. standing still will eventually get you points too 😉

There are "Moves" & "Scores". You can compete with yourself, friends & the world, to see who has the highest score with the least # of moves. e.g.; "m24s30" = 24 moves & a score of 30.

===

COW ABDUCTION -- By Francois Vander Linden
This is a HIRES two player game. Each player controls a spaceship trying to abduct humans or cows (or whatever), represented as dots on the screen. Each player uses a paddle to control a spaceship. The associated button launches the abduction-ray as long as you press the button. Press longer to reach the most distant humans/cows .... Release the button to retract the ray back to your spaceship ... wait until the ray is back to your ship so you can move to another location ... humans/cows are on screen, the most distant give the most points ... abduct as many as possible and try to beat your opponent !


===

AQUATRON -- By Brett Butler

You are AquaTron, the legendary defender of Applentis. An ancient virtual civilization hidden in the deepest depths of the digital ocean. As AquaTron, you must rigorously protect the secret existence of Applentis from outsider paparazzi bubbles. These paparazzi bubble scourge will do anything to get close enough to your Applentis to snap photos as evidence of its existence, so they can sell their pictures to the disgusting C64 tabloid publications of the fringe Above-Grounders. Use your 3 laser blast stations to blast blinding flashes of petrifying light at the latest paparazzi bubble who has discovered the existence of Applentis. You have to hit the paparazzi bubble directly to score points. The public of Applentis is keeping count of your laser blasts, number of direct hits and your hit-ratio %. Be careful how you use your laser blasts to not waste your civilization’s vital energy. Your people will use your final stats to determine how you will be ranked.
Ranking:
Epic Blaster Master : Laser Blasts >=80, Score>=10, Hit Ratio = 100%
Trusted Defender : Laser Blasts >=60, Hit Ratio = 80% - 99%
Precision Kernal: Laser Blasts >=40, Hit Ratio = 40% - 79%
Major Twitcher : Laser Blasts >=20, Hit Ratio = 20% - 39%
Private Bubble Lover : Laser Blasts >=10, Hit Ratio = 1% - 19%
Keys
]RUN = start game
[1] = laser blast from left station
[2] = laser blast from middle station
[3] = laser blast from right station
[CTRL][C] = quit game

===

POOR MANS GYRUS -- By Brett Butler

Brett Butler Here's a 3rd submission. It's not 100% what I'm hoping for yet, but thought I'd put it out here. It's like a poor man's Gyrus. Circle around and fire inward at the enemy ship. Still needs a name. Any ideas?
Lowercase Keys during game play:
]RUN = start game
[z] = rotate clockwise
[x] = rotate counter-clockwise
[y] = fire
[CTRL][C] = quit game
Scoring:
If you hit the enemy you get another point.

===
THE LAST BATTLE OF THE 23 GUNS OF FORT ALAMOON -- By Francois Vander Linden

Fort Alamoon is a human base on the moon equipped with 23 laser turrets labeled A thru W.
This day, the evil alien race, the Klzrgzwxzc (that's how =they= pronounce it -- don't blame me, these things are not made up), have decided to attack Fort Alamoon ... their next stop will certainly be planet Earth ...
Fort Alamoon is doomed but how long can you hold ? Maybe if you fight bravely enough, reinforcements from earth will arrive in time ....
Activate each laser turret by pressing the letter corresponding to its name ... obliterate the evil Klzrgzwxzc or at least try to repel them before they reach your lines !
Some of the aliens are slow, and some are pretty fast !
A thrilling fast-paced action game with increasing difficulty and sound effects (well, actually one sound effect) !

===

PLAYA -- By Brett Butler

Time to jam out like it’s 1981 on your 8-BIT Guitar. Play all the popular songs from the 80's. Just amazing how they all fit in 2 lines of code.
DIFFICULTLY LEVELS:
{1} Beginner Playa:
]HOME
Then hit [RETURN] 9 times.
]RUN
{2} Advanced Playa: no need to look at your guitar strings. This hides the note keys:
]HOME
]RUN
PLAYING:
Type the key [1] … [9] before the Note reaches the lower play-bar in the #’s column. If you played the correct note, you'll hear it when the note is inside the lower play-bar. If you blew it, you won't hear the distinct note played.
END GAME:
[CTRL][C]

===

THE ATROCIOUS-HORRENDOUS PURPLE AND GREEN FLESH EATING CATERPILLARS FROM OUTER SPACE ARE INVADING EARTH -- By Francois Vander Linden

The game is called "The atrocious-horrendous purple and green flesh-eating caterpillars from outer-space are invading the Earth" ... or more simply "Caterpillars". 🤣
You control a laser-turret at the bottom of the screen using your joystick. The caterpillars slowly come from the top of the screen. Stop them before they reach the ground !
Press and hold the button to charge your laser. The more you charge your laser the more segments of the caterpillar you'll blow away. Each destroyed segment is worth one point. How long will you hold ?
The game exists in two versions: a 2-liner reduced-version without sound and with slower caterpillars (but also a less effective laser turret to balance the difficulty) and a 3-lines version that includes the whole shebang.
The game uses Applesoft shape tables to draw the caterpillars, the laser turret and the laser shot (those last two are using the same shape actually).
This game introduces a very nice trick I have never seen elsewhere. I'm not saying it hasn't been used in the past (because it has some restrictions) but in case of two-liners where each character counts, it's a nice trick, I'm kind of proud of it.
Here goes: usually when defining shape tables you'll have a loop reading DATA to be POKEd. The problem is that this uses a lot of characters just to poke a few bytes. So I was thinking how could I compress this ? Each character is a byte-value in itself. It's the smallest form of byte representation. All the printed characters are located in text page 1 ($400-$7FF). What if I PRINT in text page 1 the bytes needed for my shape table ? It turns out that building shape tables can be done using bytes lower than 64. All these bytes, when "printed" are INVERSE characters. So all I have to do is build a shape table with bytes lower than 64 and print them in INVERSE on the screen. Of course I can't scroll the screen or I'm losing my shape table.
It turns out that it works pretty well. You just have to make sure that the last 2-bits movement for each byte in the shape table equals "00" (meaning "ignore") (this will ensure bytes < 64)
So instead of having this:
FORI=1TO18:READA:POKE768+I,A:NEXT:DATA2,0,6,0,8,0,4,0,18,63,32,36,41,45,50,54,59,0
(83 characters)
I have this:
HOME:INVERSE:?"B@F@H@D@R? $)-26;@"
(34 characters)
I saved 49 characters !
Another trick I use here:
In a 2-liner we can't use IFs so in order to not draw shapes when they're not needed, I simply draw them below the 159 pixels limit of HGR ... so in fact they are drawn but you just can't see them because their hidden by the 4 lines of text of HGR.
I hope you liked these tricks and enjoy the game ! Happy coding ! (a DSK will be published in another post)

===

SPIDER CRAWLER -- By Francois Vander Linden

Help a little spider reach the other end of the screen ...

The house she lives in is very old and the floor as well as the ceiling have a lot of cracks which appear like chasms to her.

Help the little spider jump over those cracks ! Press any key and she'll jump on the ceiling or fall back to the floor ...

Be prepared, like any real spider, she's really running fast, so be prepared ! And have fun !

There's no special techy stuff that hasn't been used before I think ... I use two shape tables for the animation of the spider (using my trick to PRINT the shape table)... what else ? mmh ...  I've NOT used a FOR STEP/NEXT loop ... the STEP is replaced by an addition within the loop ... this makes the whole stuff go faster .... and that's all I guess  ... (?)

===

ROCKS by Don Lewis

Use A and Z to control your player to avoid the rocks (or are you the rock avoiding blue puddles? ;) )

===

MIND THE GAPS By Lee Fastenau
Joystick required.

===

SLITHER By SELLAM Abraham

Use arrow keys to play -- eat green dots to grow your snake bigger, red dots will cause your snake to shrink. Don't die!
BE SURE TO TRY THE FULL DISK IMAGE VERSION OF THIS GAME WITH LOGO AND INTRO AS WELL!

A brief story of this game that almost wasn't:

I kid you not, I almost lost it all a second time, in fact it was lost, but I stormed into hell and rebuked satan, found the code and resurrected it.

This may seem like me being dramatic but I swear this game is cursed, play it or even load it on your computer at your own peril.

I think i tapped into dark forces with the theme.

Right when i had that intro all done, i'm not sure exactly what happened, might've had to do with running two instances of linapple at once, i don't know, but the intro i spent all f_cking day on was just gone, literally right before i was going to upload it.

I was about to try to re-type the entire damn thing but i was like, no, no, no, no, I am not going this fucking thing all over, the code has to still be there.

I searched the disk image in linux, there it was. the program was there, i just needed to figure out where it was on the disk in the emulator, read in those blocks, and re-assemble it.

I brushed up real quick on the ProDOS MLI, wrote some quick code to read blocks and print out the results, after a little while I worked out where it was stored, loaded those blocks into memory, copied them back down into the BASIC space, fixed the program length pointers, saved it, got it.

PHEW

This is ridiculous!

The last thing i did was re-type the f_cking two-line program in AGAIN for like the fifth time.

I can't believe i did all this work for a f_cking two-line program!

=== 

Unamed OffRoad Game by Francois Vander Linden

OK, nothing exceptional here (as I think similar stuff has been done before), but it's the first two-liner I've ever finished (Ive made others but was dissatisfied with the result). Use J and L to control the car on the desert road track ... any other key to stop ...

===

Descent Into The Dark and Gloomy Depths of Uranus. Episode 4: A New Probe by Francois Vander Linden

Backstory:

The Allied Forces of Earth have discovered that Uranus is pretty much a big cheese: beneath the planet's surface lies a gigantic labyrinth of gloomy caverns giving shelter to new amazing (yet disgusting) life forms.
A first scientific expedition was sent to explore those caves but never returned.
It's time to get your hands dirty !
You are Colonel O'Scopy and you pilot a new kind of probe ship specially designed to map those caverns.
Use the joystick to carefully maneuver the probe inside the gloomy tunnels of your Uranus. Watch out : don't crash your probe on the walls of these narrow passageways or you'll probably die a horrible death among the amorphous lifeforms that haunts those horrendous stinky caves.
Will you find the first expedition ? Will your probe see the light of day again ? Only a skilled pilot with steady hands and nerves of steel can control the probe ship deep enough in the caverns of Uranus and return with a nice surprise !
Enjoy ! :D

Technical notes:

Nothing really new here. I'm still using PRINTed shapetables (explanation in another post).
The "caves generator" takes most of the code. At first, the caves were drawn faster with a new "edge" every 4 pixels and linking all the edges using HPLOT TO X,Y but it produced longer code because I had to draw a line for the upper wall and one for the lower wall. So I decided to "colorize" the inside of the caves simply by drawing a white line from the upper wall to the lower wall. But it meant drawing a new edge for every X coordinate (otherwise I would have had stripes). Finally by using purple as the color (and not white) I have accelerated the process by 2 (since a vertical color line is really a black line + a color line).
I worked hard to tweak the settings so the "caves generator" produces really variable landscapes. Sometimes it will be a narrow passageway and sometimes it will begin or end with a giant caveroom with a lot of space and sometimes a mix of everything.
The probe has various speeds: from 0 to 4 in X/Y directions. The code for that is really simple.
DX = INT( (PDL(0) - 127) / 30). This will give you a integer between -4 and +4. The "optimized" equivalent is simply
DX = INT( (PDL(0) / 30 - 4).
Usually when you move something (a ship, a character, an enemy), you have to make sure you're still within the screen limits. IN 2-liner optimized code this is done usually with something like:
Y = Y * (Y>=0 AND Y<=159) + 159 * (Y>159)
This code will make sure 0 <= Y <= 159. The first multiplication means that if Y is between 0 and 159 (this condition returns 1) you keep the value of Y (Y*1). But (second part/multiplication), if Y > 159 (true returns 1) you use 159 (159*1). Notice that you don't have to use a third condition to make sure Y>=0 because if the first two conditions fail you will have Y = 0 + 0 = 0 anyway.
Well at first this game had such a condition for Y until I realized I didn't need to check for those limits because if the ship hits a wall either up or down the game is over. This saved a few characters.
To check for collision I use the collision counter located in $EA (234) ... as you know it counts the pixels that had to be toggled in order to draw a shape ... because the background is always purple it's possible to use the counter. If the ship had been drawn on a variable background it probably would not have worked.
The game fits in 2 lines of 239 characters with only a few characters left. When you're optimizing 2-liners code you sometimes have to sacrifice some features (sound, difficulty, little nice effects, ...), turn a 10 into a 9 just to save a character etc. But you also have to make sure your code fits on two lines of 239 characters long (max). Even if your code length is < 478 characters, you can't have 1 line with 248 characters and another one with 230 characters. So you end up moving parts of your code around just to have enough space on each line to cram all the instructions.
For this game, my first line was too long ... so I moved a R=273 on the second line. I was lucky it was possible to do so ...

Update for V3:

All that was missing from my previous code was a "PRINT 200-I" instead of "PRINT I" so it would display a descending counter ... All I needed was 4 characters. Unfortunately, the 2nd line was full ....
BUT ... my very first line was beginning with a FOR J=0 TO 1 loop ... the idea being that as long as you're not crashed and as long as the counter is running, J would be set to ZERO to "reset" the loop ... What if I could remove that FOR ? I could save 9 characters on the first line and maybe move some stuff from 2nd line to the first one ?
Here's how I did it: in position 200 ($C8), there is an RTS ($60). This RTS is part of the CHARGET/CHARGOT routine that is loaded by Applesoft. It's almost certain it is there !
You know that if you CALL 0 (zero), you quit the running Applesoft program. But if you CALL 200, you reach that RTS and go back as if nothing happened. All I had to do was make sure that I would CALL 0 if the player lost and CALL 200 if the player was still allowed to play.

How convenient ! That 200 number is EXACTLY the starting value I choose for the counter ! So I decided to place that 200 in a variable (F) and it saved a few more characters.

The part that handles "continue or end" is the following:
CALL(F*(PEEK(234)<11ANDI<F))
F=200. PEEK(234) is the collision counter (<11 means there's no severe collision) while I is the countdown. So if there's no collision AND if the countdown has not reached 200 (we're counting upwards -- and displaying downwards), we have a value of 1 and we multiply it by 200, which results in a CALL 200 (and the program continues). If instead we have a value of 0 for that double condition, we have a CALL 0 and the program ends.
One last thing: the last statement is "GOTO" without a line number. This is possible because I have started my program on line ZERO. GOTO doesn't need to be followed by a number if you want to go back to line ZERO. That's one more character saved (although at this point it's not really needed as I have 3 characters left !)
One last (last) thing: because it's a countdown, I had to modify the display of the counter otherwise it would leave on the screen a 0 when reaching 99 and then when reaching 9 (because there's one character less to print when going from 100 to 99 and from 10 to 9) ... So now I'm printing the counter first and then the score/level ...


=== SLALOM by Francois Vander Linden

Here comes another 2-liner game called SLALOM !

How fast can you go ? How many gates can you take ? Are you ready to take risks and fast turn so you can reach that dangerous gate and make a perfect score ? Let's discover if you have the nerves of steel of a Slalom Champion !
Use joystick to maneuver through the gates: X-axis controls your main direction while Y-axis controls your acceleration. Lift Y-axis up to slow down but notice you'll never really stop in that dangerous slope !
A DSK file with several versions of the game will be published soon.
Enjoy the game and the code explanation for those interested.
Technical stuff:
There's nothing very technical in this game, in fact it's quite simple. No extraordinary trick.
I propose however to explain to beginners how the code works by going through it statement by statement.
The game idea came while working on another 2-liner (more about that one in a few weeks ?) ... at a point I had like a white mountain with a ski trace on it ... of course it reminded me of those countless games that tried to simulate ski sports like Winter Games and some others ...
I personnally remember having read books with Basic code in them to program such a game. If I remember correctly the code was Basic but not Applesoft and it never worked ... I was 13 and frustrated ... but I've survived ! :D
The code itself is quite simple as it just reads PDL(0) & PDL(1) to draw black pixels on a white canvas with some kind of sense of speed.
An early version of the game did not feature trees, just gates ... it was so simple I had enough characters to count and print time, score and missed gates on text line 21
Then I came back to the original (unoptimized-for-2-liners code) and decided it would be great to display some trees/pines. WHAT DID I DO ??
The best I could come up with was around 100+ characters just to display ONE pine, inconceivable.
I have tried several techniques from bytes plot to HGR (poking the appropriate bytes in $2000-$3FFF like in a real Apple II game), Applesoft Shape Tables and HPLOT. Of all the techniques, HPLOT was still the shortest but even like that it was too long.
Sellam Abraham was called to the rescue and after several tries, he managed to display a pine with only 75 characters of code! Impressive ! How did he do it ? He simply changed the general shape of the pine: from two stacked green triangles + trunk, it became one larger green triangle + trunk.
Ok his tree was good-looking except on odd X-coordinates were the trunk would only be one pixel wide. But the new shape was interesting, it was simpler so maybe I could optimize the code furthermore. And I did, with only 70 characters. But then of course Sellam came back with another version with only 64 characters. Unfortunately, although very inventive, this latest version had the same problem as the one before: sometimes the trunk would only be one-pixel wide.
In the end I did go with the 70-characters version, it's only a matter of taste. Had I needed more space, I would have used Sellam's version.
Here's the final 2-lines code explained (with added spaces for clarity)
HOME : HGR : POKE 28,127 : CALL -3082
Apart from clearing the TEXT screen (only for aesthetics as we'll print some text on line 21), this clears the HGR screen to white (using HCOLOR 3).
The rest requires an explanation. The call to -3082 will clear the screen with the latest color used. Even though HCOLOR is actually stored in $E4 (228), the latest color used is really in $1C (28). Because the routine in -3082 uses the hires page pointer in $E6 (230) (which will point to hires page 1 -$20-, page 2 -$40- or page 3 -$60) and because that pointer is not set until we call HGR or HGR2, I need to place an HGR before the call to -3082. If I hadn't, then the program would crash the computer, except if there was a valid value in $E6. So all in all the screen is cleared two times: once in black, then in white.
At first, I decided I would paint the snow using white #2 (HCOLOR 7 - POKE 28,255). But drawing green trees on white bytes with hi-bit 7 set, would give red glitches from time to time. To avoid this, I decided the snow would be with bit 7 off. As it turns out, red color (hi bit 7 set) does not have the same kind of problem with its white counter-part.
X = 140 : A = X : Q = 265 : DIM D(Q)
Initializing some variables. 140 is the starting point. X will hold the x-coord of the skier. 140 is copied to A. A will be used as a starting point to randomly place the gates (x-coord). Q is a "magic number". In earlier versions it was actually 270 and was used as the rightmost limit of the hires screen (which is 279 of course). Then I noticed I had a value of 250 used in some formula elsewhere. That 250 was completely subjective. It could have been 260, 265 or 270 or anything similar. So as I had so many 250, 260, 265, 270 used everywhere, I settled for 265 and stored it in Q.
D() array will hold the x-coord of each gate on each of the 159 lines of the screen. So why dimension it to 265 ? Because it saves me 2 characters. In fact 159 (or so) were actually enough.
FOR K = 0 TO 13
Now we're going to create 14 gates and 14 trees
Z = RND(1) * X - 70 + A
B = RND(1) * 8 + 6 + B
L = 30 * (Z<11) + Q * (Z>=Q)
A = Z * NOT L + L
A and B are the X and Y-coord of each gate. For now X equals 140 and is used as a constant (although it will be used as a variable as soon as the game starts). Each gate will be separated from +69 to -69 pixels from the previous one on X-axis while its y-coord will be down from 6 to 13 pixels.
Of course, randomly choosing a X-coord for a gate relatively from the position of the previous gate requires limiting the values inside the screen or else the program would crash.
This ensures that X will stay between XMIN and XMAX. But because we're moving X from a relaive position, there's a shorter way that translates like this:
X = X * (X>XMIN AND X<XMAX) + XMAX * (X>=XMAX) + XMIN * (X<=XMIN)
This ensures that X will stay between XMIN and XMAX. But because we're moving X from a relative position, there's a shorter way that translates like this:
Z = OFFSET + X
REM Z holds now the new X value if it's within limits !
L = XMIN*(Z<=XMIN) + XMAX*(Z>=XMAX)
REM is Z actually within limits ? 0 = yes, another value means a limit (but we don't know which one) has been reached and X value should be that value.
X = Z * NOT L + L
REM store Z in X if Z is within limits or store L in X if Z is out of bounds
We now have A,B as the X,Y coords of the gate. We'll decide where to place a tree now.
C = RND(1) * 40 + 70 + A
C will hold the X-coord of the tree. Its default position is somewhere 70 to 109 pixels to the right of A.
I could have randomly chosen a left/right side but it would have meant perform another RND and as we'll see with the final result, it doesn't really matter in the end.
C = C * (C<Q) + (A-C+A) * (C>=Q)
This formula will check if C is within screen limits (actually 265 as Q equals 265). If it's not, then we place C at the opposite (left side) 70-139 pixels of A.
FOR I = 0 TO 8
T = I > 6
HCOLOR = 1 + 4 * T
J = I + (2-I)*T
HPLOT C-J , B+I-6 TO C+J-T, B+I-6
NEXT
This draws a tree, 9 pixels high. The first 7 (0-6) lines should plot green stuff. T indicates if we have reached line 7 or not.
HCOLOR equals 1 (green), or 1+4 (=5=red) if T is true.
Now we draw a triangle. From the center position (C), the following pattern is observed: lines 0 and 1 just draw 1 pixel (from C -0 to C +0), lines 2 and 3 draw from -2 to +2 (around C), lines 4 and 5 draw from -4 to +4, lines 6 and 7 draw from -6 to +6. So it's quite easy to implement this with a loop. The trick comes when we have to draw the trunk, where we're back to -2 ... but also +1 instead of +2. Because the way the colors works on hires and because the background is white, drawing 3 pixels/bits is the only way to be sure you'll always have the same red trunk width. If I had chosen 4 pixels/bits, sometimes I would have gotten 3 pixels width and sometimes 4.
D(B)=A
HCOLOR=4
HPLOT A,B TO A,B-5
HPLOT A+10,B TO A+10,B-5
Ok now that the trees are drawn, we store the x-coord (A) of the gate in D() indexing it using its y-coord (B). This particular code was actually on the first line of the 2-lines code. I've moved it on the 2nd line because I hadn't enough characters left on the first line.
Then we actually draw the gates. All this could have been done before but then I would have an incomplete (not 239 characters-long) first line.
Notice that the color of the gates is black#2 (HCOLOR 4) and that depending if A is odd or even, it will actually display red or blue (and in fact turn the hi-bit of that hi-res byte). This is great because it gives a more colorful course even though it's using only one color. And what's more, that color is the color of the skis tracks. So this is the last HCOLOR in the code. I'm pretty sure it could have been possible to use the HCOLOR in the loop of the trees to end up with HCOLOR 4 but I haven't seriously tried.
As a last note, the original code had flags on the poles of the gate. I had to get rid of that unfortunately.
NEXT
And we go on to next gate ....
HPLOT X,Y : WAIT 49249,128
Now the skier is in place (plotted in X,Y using HCOLOR 4 which will display it as a red dot) and we "WAIT" for a button #0 press.
The WAIT command is a weird command to master as it will wait for a memory location to change some bits according to the next two arguments you give. At first I had a loop like FOR I=0TO128:I=PEEK(49249):NEXT that would do the job but then remembered that WAIT could be used.
It is clear that if I was needing more characters I would have replaced this with a GETA$ ... or maybe just removed the whole statement. But giving the player the ability to decide when to start the race is a nice feature: you have the time to prepare your joystick just like a real skier knows in which direction to go first.
FOR Z= 0 TO 159
Here comes the main loop of the game and it's only 150 characters long.
The loop will use a variable from 0 to 159 which is a Y-coord. As long as the skier is not out of bounds or at the bottom of the screen, Z will reflect his INTEGER position on the screen. Its real position will be stored in Y, a FLOAT. If you make Y the looping variable, the game will be unplayable as you will move 1 pixel down each iteration of the loop (as if PDL(1) had not effect)
X = X + PDL(0) / 32 - 4
L = X<0 OR X>279
The X-coord of the skier is based on the paddle value and its offset at every run of the loop will go from -4 to +4.
At first my formula was (PDL(0) - 127)/32 which is the same (if you excuse the precision). This formula made sense to me: if it's below 127 it will be negative, it's above above, it will be positive (32 is just a divider to set "how much it would be" negative/positive). But reducing the fraction was better.
L will hold 1 if the skier is out of bounds and 0 if not. At first I had the opposite comparison:
L = X>=0 AND X<280
But as later I'm using both "NOT L" and "L" expressions, changing it to an OR instead of an AND just saved a few characters.
Y = Y + .1 + .0035 * PDL(1)
This is how the Y-coord evolves ... This came from Y = Y + .1 + (.9 * PDL(1)/255)
As I wanted the skier to feel the slope even with the joystick all the way up, the skier had to move downwards a little bit, every time. This explains the 0.1. So the actual value from PDL(1) must be scaled to 0.9. The final equation is just a simplification(.9/255 = 0.0035294). I had to round down because the skier has to go through EVERY Y-coord. Otherwise, he might miss a gate (remember the table D() is indexed on the INTEGER value of the Y-coords).
HPLOT TO X * NOT L, Y
Now we draw the ski tracks from the skier's last position to its new one ...
I've used L to zero'ed X if the skier is out of bounds. It will look ok if the skier is in x-coord zero but it will actually draw a horizontal line if the skier is on the right side of the screen. Anyway, as the game ends when the skier is out of bounds, it does not really matter. My original code included the case where the skier is on the right side of the screen (it's only "+279*(X>279)") but it required 12 characters that were needed elsewhere so I dropped this....
U=D(Y) : S = S + (U>0) * (X>=U AND X<=U+10)
Now it's time to count score. As D(Y) is used several times, I've stored it in a temp variable (U) to save a few chars. Score increases if there's a gate (D(Y)>0) and that the player is within its bounds (X>=D(Y) AND X<D(Y)+10).
D(Y)=0
This simple statement is very important as it resets the coordinate of the gate in position Y ... whether there was a gate or not, now there isn't.
This is needed because we don't move from one pixel at each iteration of the loop. Remember the smallest Y-move is 0.1 per iteration. If this statement was absent, the score would increase if the skier passed through a gate at a vertical speed slower than 1.
T=T+1
This increases the timer. Notice that you cannot win the game with a time below 159 ...
Z = Y + 159 * L
This updates the loop variable to decide if the game continues or not. If we were out of bounds, Z would be over 159 and the game will end. If we were not but Y was 159, it will be the end too.
VTAB21 : ?T,S : NEXT
This just prints the time and score and concludes the game loop.
One last word about the FOR/NEXT game loop. I have checked and yes, it could be replaced by an appropriate POKE 184 at the end of line 2, saving a few characters. The POKE 184 is a technique that Sellam Abraham used to simulate a GOTO in Applesoft program by modifying the internal pointer to the next token in the Applesoft code. That pointer is stored in memory position 184.

